package com.gm.commonlib.util.fileUtil;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Bitmap.CompressFormat;
import android.os.Environment;
import android.util.Log;


import com.gm.commonlib.interfaces.IResultListener;

import java.io.BufferedOutputStream;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.Reader;
import java.io.Writer;
import java.nio.channels.FileChannel;

public class FileUtils {

    private final static String TAG = "FileUtil";
    private static int FILESIZE = 1024;

	/**
	 * 在SD卡上创建文件
	 *
	 * @param filePathAndName
	 * @return
	 * @throws IOException
	 */
	public static File createSDFile(String filePathAndName) throws IOException {
		File file = new File(filePathAndName);
		if (file.exists()) {
			file.delete();
		}
		boolean ret = file.createNewFile();
		Log.e("TEST", "createSDFile:" + ret);
		return file;
	}

	/**
	 * 写文件到SD Card
	 *
	 * @param path
	 * @param fileName
	 * @param content
	 * @return
	 */
	public static File createSDFile(String path, String fileName, String content) {
		InputStream is = String2InputStream(content);
		return write2SDFromInput(path, fileName, is);
	}

	public static InputStream String2InputStream(String str) {
		ByteArrayInputStream stream = new ByteArrayInputStream(str.getBytes());
		return stream;
	}

	/**
	 * 写文件到SD Card
	 *
	 * @param data
	 * @param path
	 * @param fileName
	 * @return
	 */
	public static File createSDFile(byte[] data, String path, String fileName) {
		return write2SDCard(data, path, fileName);
	}

	/**
	 * 复制文件
	 *
	 * @param fromFile 要复制的文件
	 * @param toFolder 复制到那个目录
	 * @param fileName 复制后的文件名称
	 * @return 复制后的文件
	 */
	public static File copyFile(File fromFile, File toFolder, String fileName) throws Exception {
		if (fromFile == null || !fromFile.isFile() || !fromFile.exists()) {
			throw new Exception("源参数错误");
		}

		if (toFolder == null || fileName == null || "".equals(fileName)) {
			throw new Exception("目标参数错误");
		}

		if (!isFileExists(toFolder)) {
			boolean isSuccess = toFolder.mkdirs();
			if (!isSuccess) {
				throw new Exception("创建文件夹失败!");
			}
		}

		final File targetFile = new File(toFolder, fileName);
		createNewFile(targetFile);

		if (!isFileExists(targetFile)) {
			throw new Exception("创建新文件失败!");
		}


		openFileAsInputStream(fromFile, new IResultListener<InputStream>() {
			@Override
			public void onResult(InputStream result) {
				StreamUtil.scanStream(result, new StreamUtil.FileStreamScanListener(targetFile));
			}
		});

		return targetFile;
	}

	public static void openFileAsInputStream(File file, IResultListener<InputStream> resultListener) {
		if (file == null || resultListener == null || !file.exists()) {
			Log.e(TAG, "null parameter or not exists");
			return;
		}

		InputStream inputStream = null;
		try {
			inputStream = new FileInputStream(file);
			resultListener.onResult(inputStream);
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			StreamUtil.close(inputStream);
		}
	}


	/**
	 * 在SD卡上创建目录
	 *
	 * @param
	 * @return
	 */
	public static File createSDDir(String path) {
		File dir = new File(path);
		if(!dir.exists()){
			boolean ret = dir.mkdirs();
			Log.e("FileUtils", "createSDDir:" + ret);
		}
		return dir;
	}

	/**
	 * 创建目录
	 *
	 * @param context
	 * @param dirName
	 *            文件夹名称
	 * @return
	 */
	public static File createFileDir(Context context, String dirName) {
		String filePath;
		// 如SD卡已存在，则存储；反之存在data目录下
		if (hasSdcard()) {
			// SD卡路径
			filePath = Environment.getExternalStorageDirectory() + File.separator + dirName;
		} else {
			filePath = context.getCacheDir().getPath() + File.separator + dirName;
		}
		File destDir = new File(filePath);
		if (!destDir.exists()) {
			boolean isCreate = destDir.mkdirs();
			Log.i("FileUtils", filePath + " has created. " + isCreate);
		}
		return destDir;
	}


	/**
	 * 判断某目录下文件是否存在
	 *
	 * @param dir
	 *            目录
	 * @param fileName
	 *            文件名
	 * @return
	 */
	public static boolean isFileExists(File dir, String fileName) {
		return new File(dir, fileName).exists();
	}


	/**
	 * 获取文件大小，单位为byte（若为目录，则包括所有子目录和文件）
	 *
	 * @param file
	 * @return
	 */
	public static long getFileSize(File file) {
		long size = 0;
		if (file.exists()) {
			if (file.isDirectory()) {
				File[] subFiles = file.listFiles();
				if (subFiles != null) {
					int num = subFiles.length;
					for (int i = 0; i < num; i++) {
						size += getFileSize(subFiles[i]);
					}
				}
			} else {
				size += file.length();
			}
		}
		return size;
	}

	/**
	 * 删除SD卡上的文件
	 *
	 * @param fileName
	 * @return
	 */
	public static boolean delSDFile(String path, String fileName) {
		File file = new File(path + fileName);
		return file.delete();
	}

	/**
	 * 删除指定目录下的所有文件
	 *
	 * @param folderPath
	 *            目录路径
	 * @return true:删除成功 false:删除失败
	 */
	public static boolean delAllFile(String folderPath) {
		boolean flag = false;
		File file = new File(folderPath);
		if (!file.exists()) {
			return flag;
		}
		if (!file.isDirectory()) {
			return flag;
		}
		String[] tempList = file.list();
		if(tempList == null) {
			return flag;
		}
		File temp = null;
		for (int i = 0; i < tempList.length; i++) {
			if (folderPath.endsWith(File.separator)) {
				temp = new File(folderPath + tempList[i]);
			} else {
				temp = new File(folderPath + File.separator + tempList[i]);
			}
			if (temp.isFile()) {
				temp.delete();
			}
			if (temp.isDirectory()) {
				delAllFile(folderPath + "/" + tempList[i]);// 先删除文件夹里面的文件
				delFolder(folderPath + "/" + tempList[i]);// 再删除空文件夹
				flag = true;
			}
		}
		return flag;
	}

	/**
	 * 删除指定文件
	 *
	 * @param filePath
	 *            指定文件的路径
	 * @return true:删除成功 false:删除失败
	 */
	public static boolean delFile(String filePath) {
		boolean flag = false;
		File file = new File(filePath);
		if (!file.exists()) {
			return flag;
		}
		flag = (new File(filePath)).delete();
		return flag;
	}

	/**
	 * 删除指定文件夹(包括文件夹下的所有文件)
	 *
	 * @param folderPath
	 *            指定文件夹路径
	 * @return true:删除成功 false:删除失败
	 */
	public static boolean delFolder(String folderPath) {
		try {
			delAllFile(folderPath); // 删除完里面所有内容
			String filePath = folderPath;
			filePath = filePath.toString();
			File myFilePath = new File(filePath);
			myFilePath.delete(); // 删除空文件夹
		} catch (Exception e) {
			e.printStackTrace();
			return false;
		}
		return true;
	}

	/**
	 * 删除文件（若为目录，则递归删除子目录和文件）
	 *
	 * @param file
	 * @param delThisPath
	 *            true代表删除参数指定file，false代表保留参数指定file
	 */
	public static void delFile(File file, boolean delThisPath) {
		if (!file.exists()) {
			return;
		}
		if (file.isDirectory()) {
			File[] subFiles = file.listFiles();
			if (subFiles != null) {
				int num = subFiles.length;
				// 删除子目录和文件
				for (int i = 0; i < num; i++) {
					delFile(subFiles[i], true);
				}
			}
		}
		if (delThisPath) {
			file.delete();
		}
	}


	/**
	 * 将一个InputStream里面的数据写入到SD卡中
	 *
	 * @param path
	 * @param fileName
	 * @param input
	 * @return
	 */
	public static File write2SDFromInput(String path, String fileName,
			InputStream input) {
		File file = null;
		OutputStream output = null;
		int size = 0;
		try {
			createSDDir(path);
			// ---------------
			file = createSDFile(path + fileName);
			output = new FileOutputStream(file);
			byte[] buffer = new byte[FILESIZE];
			while ((size = input.read(buffer)) != -1) {
				output.write(buffer, 0, size);
			}
			output.flush();
			// -----------

		} catch (Exception e) {
			Log.e("TEST", "write the inputstream to SD failed, e:" + e.getLocalizedMessage());
		} finally {
			try {
				if (null != input) {
					input.close();
				}
				if (null != output) {
					output.close();
				}
			} catch (IOException e) {

			}
		}
		return file;
	}

	private static File write2SDCard(byte[] data, String path, String fileName) {
		File file = null;
		FileOutputStream fos = null;
		try {
			createSDDir(path);
			file = createSDFile(path + fileName);
			fos = new FileOutputStream(file);
			fos.write(data);
			fos.flush();
		} catch (Exception e) {
			Log.e("TEST", "write the inputstream to SD failed, e:" + e.getLocalizedMessage());
		} finally {
			try {
				if (fos != null) {
					fos.close();
				}
			} catch (IOException e) {

			}
		}
		return file;
	}

	/**
	 * 保存Bitmap到指定目录
	 *
	 * @param dir
	 *            目录
	 * @param fileName
	 *            文件名
	 * @param bitmap
	 * @throws IOException
	 */
	public static void savaBitmap(File dir, String fileName, Bitmap bitmap) {
		if (bitmap == null) {
			return;
		}
		File file = new File(dir, fileName);
		try {
			file.createNewFile();
			FileOutputStream fos = new FileOutputStream(file);
			bitmap.compress(CompressFormat.JPEG, 100, fos);
			fos.flush();
			fos.close();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}




    public static void makeFolderExists(File file) {
        if (file != null && !file.exists()) {
            file.mkdirs();
        }

    }

    public static void makeFileExists(File file) {
        if (file == null) {
            return;
        }
        if (!file.exists()) {
            makeFolderExists(file.getParentFile());
            try {
                file.createNewFile();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    public static void createNewFile(File file) {
        if (file == null) {
            return;
        }
        if (!file.exists()) {
            try {
                file.createNewFile();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    public static boolean isFileExists(File file) {
        if (file == null) {
            return false;
        }

        return file.exists();
    }



    //TODO 获取包含 . 号的扩展名
    public static String getFullExtensionName(String filename) {
        if (filename == null || !filename.contains(".")) {
            return "";
        }

        int dot = filename.lastIndexOf('.');
        if ((dot > -1) && (dot < (filename.length() - 1))) {
            return filename.substring(dot);
        }
        return "";
    }

    public static File createSDDir(File folder) {
        if (folder != null && !folder.exists()) {
            boolean var2 = folder.mkdirs();
            Log.e("FileUtils", "createSDDir:" + var2);
        }

        return folder;
    }

    public static File createSDFile(File folder, String fileName) throws IOException {
        return createSDFile(new File(folder, fileName), true);
    }

    public static File createSDFile(File file, boolean recover) throws IOException {
        if (file == null) {
            return file;
        }

        if (recover && file.exists()) {
            file.delete();
        }

        boolean var2 = file.createNewFile();
        Log.e("TEST", "createSDFile:" + var2);
        return file;
    }



    /**
     * 判断sdcard是否被挂载
     */
    public static boolean hasSdcard() {
        if (Environment.MEDIA_MOUNTED.equals(Environment.getExternalStorageState())) {
            return true;
        } else {
            return false;
        }
    }

    public static void syncCleanFolder(final File folder) {
    	try{
			if (folder != null && folder.exists()) {
				new Thread(new Runnable() {
					@Override
					public void run() {
						File[] files = folder.listFiles();
						if (files != null) {
							for (File file : files) {
								file.delete();
							}
						}
					}
				}).start();
			}
		}
		catch (Exception e){

		}

    }

    /**
     * 判断SDCard是否存在 [当没有外挂SD卡时，内置ROM也被识别为存在sd卡]
     *
     * @return
     */

    public static boolean isSdCardExist() {

        return Environment.getExternalStorageState().equals(

                Environment.MEDIA_MOUNTED);

    }

    public static String getSdCardPath() {
        boolean exist = isSdCardExist();

        String sdpath = "";

        if (exist) {
            sdpath = Environment.getExternalStorageDirectory()
                    .getAbsolutePath();
        } else {
            sdpath = null;
        }
        return sdpath;


    }

    //保存压缩后的图片
    public static void saveFile(final Bitmap bitmap, final File file) {
        new Thread(new Runnable() {
            @Override
            public void run() {
                if (file.exists()) {
                    file.delete();
                }
                try {
                    file.createNewFile();
                    BufferedOutputStream bos = null;
                    bos = new BufferedOutputStream(
                            new FileOutputStream(file));
                    bitmap.compress(CompressFormat.JPEG, 60, bos);
                    bos.flush();
                    bos.close();
                } catch (Exception e) {
                    e.printStackTrace();
                }

            }
        }).start();

    }


}
